//
// Created by lqx on 2021/8/21.
//

#include <netinet/in.h>
#include <iostream>
#include <sys/epoll.h>
#include <thread>
#include "epoll_server.h"

void Worker1(int socketFd, int k) {
    std::cout << " Worker" << k << " run " << std::endl;
    while (true) {
        int tfd = 0;
        sockaddr_in cli_addr{};
        socklen_t length = sizeof(cli_addr);
        std::cout << "worker" << k << " in " << std::endl;
        tfd = accept(socketFd, (sockaddr *) &cli_addr, &length);
        if (tfd <= 0) {
            std::cout << "accept error" << std::endl;
            return;
        } else {
            std::cout << "worker" << k << " accept " << std::endl;
        }
    }
}

void Worker2(int socketFd, int k) {
    std::cout << " Worker" << k << " run " << std::endl;

    int eFd = epoll_create(1);
    if (eFd < 0) {
        std::cout << "create epoll fail";
        return;
    }
    epoll_event epev_{};
    epev_.events = EPOLLIN;
    epev_.data.fd = socketFd;
    epoll_ctl(eFd, EPOLL_CTL_ADD, socketFd, &epev_);
    epoll_event events[EVENT_NUM];

    while (true) {
        int eNum = epoll_wait(eFd, events, EVENT_NUM, -1);
        if (eNum == -1) {
            std::cout << "epoll error";
            return;
        }
        //一定要加上这句,防止事件被瞬间处理,导致看不到结果
        std::this_thread::sleep_for((std::chrono::seconds(1)));
        std::cout << "worker" << k << " in " << std::endl;
        for (int i = 0; i < eNum; ++i) {
            if (events[i].data.fd == socketFd) {
                int tfd = 0;
                sockaddr_in cli_addr{};
                socklen_t length = sizeof(cli_addr);
                tfd = accept(socketFd, (sockaddr *) &cli_addr, &length);
                if (tfd <= 0) {
                    std::cout << "accept error" << std::endl;
                } else {
                    std::cout << "worker" << k << " accept " << std::endl;
                }
            } else {
                //处理正常的socket读写事件,这里可以忽略,不是这次关注的点
            }
        }
    }
}

void Worker3(int socketFd, int k) {
    std::cout << " Worker" << k << " run " << std::endl;

    int eFd = epoll_create(1);
    if (eFd < 0) {
        std::cout << "create epoll fail";
        return;
    }
    epoll_event epev_{};
    //给epoll加上 互斥标志
    epev_.events = EPOLLIN | EPOLLEXCLUSIVE;
    epev_.data.fd = socketFd;
    epoll_ctl(eFd, EPOLL_CTL_ADD, socketFd, &epev_);
    epoll_event events[EVENT_NUM];

    while (true) {
        int eNum = epoll_wait(eFd, events, EVENT_NUM, -1);
        if (eNum == -1) {
            std::cout << "epoll error";
            return;
        }
        //一定要加上这句,防止事件被瞬间处理,导致看不到结果
        std::this_thread::sleep_for((std::chrono::seconds(1)));
        std::cout << "worker" << k << " in " << std::endl;
        for (int i = 0; i < eNum; ++i) {
            if (events[i].data.fd == socketFd) {
                int tfd = 0;
                sockaddr_in cli_addr{};
                socklen_t length = sizeof(cli_addr);
                tfd = accept(socketFd, (sockaddr *) &cli_addr, &length);
                if (tfd <= 0) {
                    std::cout << "accept error" << std::endl;
                } else {
                    std::cout << "worker" << k << " accept " << std::endl;
                }
            } else {
                //处理正常的socket读写事件,这里可以忽略,不是这次关注的点
            }
        }
    }
}

void Worker4(int k) {
    std::cout << " Worker" << k << " run " << std::endl;

    int socketFd = createSocket2();
    int eFd = epoll_create(1);
    if (eFd == -1) {
        std::cout << "create epoll fail" << std::endl;
        return;
    }

    epoll_event epev_{};
    epev_.events = EPOLLIN;
    epev_.data.fd = socketFd;
    epoll_ctl(eFd, EPOLL_CTL_ADD, socketFd, &epev_);
    epoll_event events[EVENT_NUM];

    while (true) {
        int eNum = epoll_wait(eFd, events, EVENT_NUM, -1);
        if (eNum == -1) {
            std::cout << "epoll error" << std::endl;
            return;
        }
        std::this_thread::sleep_for((std::chrono::seconds(1)));
        std::cout << "worker" << k << " in " << std::endl;
        for (int i = 0; i < eNum; ++i) {
            if (events[i].data.fd == socketFd) {
                int tfd = 0;
                sockaddr_in cli_addr{};
                socklen_t length = sizeof(cli_addr);
                tfd = accept(socketFd, (sockaddr *) &cli_addr, &length);
                if (tfd <= 0) {
                    std::cout << "accept error" << std::endl;
                } else {
                    std::cout << "worker" << k << " accept " << std::endl;
                }
            } else {
                //处理正常的socket读写事件
            }
        }
    }
}

int createSocket() {
    int fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (fd < 0) {
        std::cout << "create socket error" << std::endl;
        return 0;
    }

    sockaddr_in sockAddr{};
    sockAddr.sin_port = htons(PORT);
    sockAddr.sin_family = AF_INET;
    sockAddr.sin_addr.s_addr = htons(INADDR_ANY);

    if (bind(fd, (sockaddr *) &sockAddr, sizeof(sockAddr)) < 0) {
        std::cout << "bind socket error, port:" << PORT << std::endl;
        return 0;
    }

    if (listen(fd, 100) < 0) {
        std::cout << "listen port error" << std::endl;
        return 0;
    }
    return fd;
}

int createSocket2() {
    int fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (fd == -1) {
        std::cout << "create socket error" << std::endl;
        return 0;
    }

    int on = 1;
    if (setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, (const void *) &on, sizeof(on)) < 0) {
        std::cout << "set opt error, ret:" << std::endl;
    }

    sockaddr_in sockAddr{};
    sockAddr.sin_port = htons(PORT);
    sockAddr.sin_family = AF_INET;
    sockAddr.sin_addr.s_addr = htons(INADDR_ANY);

    if (bind(fd, (sockaddr *) &sockAddr, sizeof(sockAddr)) < 0) {
        std::cout << "bind socket error, port:" << PORT << std::endl;
        return 0;
    }

    if (listen(fd, 100) < 0) {
        std::cout << "listen port error" << std::endl;
        return 0;
    }
    return fd;
}

